"""
数据管理模块
提供数据导入导出、备份恢复、报告生成等功能
"""

import json
import csv
import os
import zipfile
import shutil
from datetime import datetime, timedelta
from typing import Dict, List, Tuple, Any, Optional
from io import StringIO

from models.task import Task
from services.task_service import TaskService


class DataManager:
    """数据管理器"""
    
    def __init__(self, task_service: TaskService):
        """
        初始化数据管理器
        
        Args:
            task_service: 任务服务实例
        """
        self.task_service = task_service
    
    def import_from_json(self, file_path: str, mode: str = 'skip') -> Tuple[bool, str, Optional[Dict]]:
        """
        从 JSON 文件导入任务
        
        Args:
            file_path: JSON 文件路径
            mode: 合并模式 ('skip', 'update', 'replace')
            
        Returns:
            (成功标志, 消息, 统计信息)
        """
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            # 验证数据格式
            if not isinstance(data, list):
                if isinstance(data, dict) and 'tasks' in data:
                    tasks_data = data['tasks']
                else:
                    return False, "无效的 JSON 格式，期望任务列表", None
            else:
                tasks_data = data
            
            stats = {
                'total': len(tasks_data),
                'imported': 0,
                'skipped': 0,
                'updated': 0,
                'errors': 0
            }
            
            for task_data in tasks_data:
                try:
                    # 验证必需字段
                    if 'title' not in task_data:
                        stats['errors'] += 1
                        continue
                    
                    # 检查是否存在相同标题的任务
                    existing_tasks = self.task_service.search_tasks(task_data['title'], ['title'])
                    existing_task = None
                    for task in existing_tasks:
                        if task.title == task_data['title']:
                            existing_task = task
                            break
                    
                    if existing_task:
                        if mode == 'skip':
                            stats['skipped'] += 1
                            continue
                        elif mode == 'update':
                            # 更新现有任务
                            updates = {}
                            if 'description' in task_data:
                                updates['description'] = task_data['description']
                            if 'priority' in task_data:
                                updates['priority'] = task_data['priority']
                            if 'status' in task_data:
                                updates['status'] = task_data['status']
                            if 'category' in task_data:
                                updates['category'] = task_data['category']
                            if 'due_date' in task_data and task_data['due_date']:
                                try:
                                    updates['due_date'] = datetime.fromisoformat(task_data['due_date']).date()
                                except:
                                    pass
                            
                            if updates:
                                success, _ = self.task_service.edit_task(existing_task.id, **updates)
                                if success:
                                    stats['updated'] += 1
                                else:
                                    stats['errors'] += 1
                            else:
                                stats['skipped'] += 1
                            continue
                    
                    # 创建新任务
                    due_date = None
                    if 'due_date' in task_data and task_data['due_date']:
                        try:
                            due_date = datetime.fromisoformat(task_data['due_date']).date()
                        except:
                            pass
                    
                    success, _, _ = self.task_service.add_task(
                        title=task_data['title'],
                        description=task_data.get('description'),
                        priority=task_data.get('priority', 'medium'),
                        category=task_data.get('category'),
                        due_date=due_date
                    )
                    
                    if success:
                        stats['imported'] += 1
                        
                        # 如果有状态信息，更新状态
                        if 'status' in task_data and task_data['status'] != 'todo':
                            # 获取刚创建的任务
                            new_tasks = self.task_service.search_tasks(task_data['title'], ['title'])
                            for task in new_tasks:
                                if task.title == task_data['title']:
                                    self.task_service.edit_task(task.id, status=task_data['status'])
                                    break
                    else:
                        stats['errors'] += 1
                        
                except Exception as e:
                    stats['errors'] += 1
                    continue
            
            message = f"导入完成"
            return True, message, stats
            
        except Exception as e:
            return False, f"导入失败: {str(e)}", None
    
    def import_from_csv(self, file_path: str, mode: str = 'skip') -> Tuple[bool, str, Optional[Dict]]:
        """
        从 CSV 文件导入任务
        
        Args:
            file_path: CSV 文件路径
            mode: 合并模式 ('skip', 'update', 'replace')
            
        Returns:
            (成功标志, 消息, 统计信息)
        """
        try:
            tasks_data = []
            
            with open(file_path, 'r', encoding='utf-8') as f:
                reader = csv.DictReader(f)
                for row in reader:
                    tasks_data.append(row)
            
            # 转换为标准格式并调用 JSON 导入逻辑
            return self.import_from_json_data(tasks_data, mode)
            
        except Exception as e:
            return False, f"CSV 导入失败: {str(e)}", None
    
    def import_from_json_data(self, tasks_data: List[Dict], mode: str = 'skip') -> Tuple[bool, str, Optional[Dict]]:
        """
        从任务数据列表导入
        
        Args:
            tasks_data: 任务数据列表
            mode: 合并模式
            
        Returns:
            (成功标志, 消息, 统计信息)
        """
        stats = {
            'total': len(tasks_data),
            'imported': 0,
            'skipped': 0,
            'updated': 0,
            'errors': 0
        }
        
        for task_data in tasks_data:
            try:
                # 验证必需字段
                if 'title' not in task_data or not task_data['title'].strip():
                    stats['errors'] += 1
                    continue
                
                # 检查是否存在相同标题的任务
                existing_tasks = self.task_service.search_tasks(task_data['title'], ['title'])
                existing_task = None
                for task in existing_tasks:
                    if task.title == task_data['title']:
                        existing_task = task
                        break
                
                if existing_task:
                    if mode == 'skip':
                        stats['skipped'] += 1
                        continue
                    elif mode == 'update':
                        # 更新现有任务
                        updates = {}
                        if 'description' in task_data:
                            updates['description'] = task_data['description']
                        if 'priority' in task_data and task_data['priority'] in ['high', 'medium', 'low']:
                            updates['priority'] = task_data['priority']
                        if 'status' in task_data and task_data['status'] in ['todo', 'in_progress', 'completed']:
                            updates['status'] = task_data['status']
                        if 'category' in task_data:
                            updates['category'] = task_data['category']
                        if 'due_date' in task_data and task_data['due_date']:
                            try:
                                if isinstance(task_data['due_date'], str):
                                    updates['due_date'] = datetime.fromisoformat(task_data['due_date']).date()
                                else:
                                    updates['due_date'] = task_data['due_date']
                            except:
                                pass
                        
                        if updates:
                            success, _ = self.task_service.edit_task(existing_task.id, **updates)
                            if success:
                                stats['updated'] += 1
                            else:
                                stats['errors'] += 1
                        else:
                            stats['skipped'] += 1
                        continue
                
                # 创建新任务
                due_date = None
                if 'due_date' in task_data and task_data['due_date']:
                    try:
                        if isinstance(task_data['due_date'], str):
                            due_date = datetime.fromisoformat(task_data['due_date']).date()
                        else:
                            due_date = task_data['due_date']
                    except:
                        pass
                
                success, _, new_task = self.task_service.add_task(
                    title=task_data['title'],
                    description=task_data.get('description'),
                    priority=task_data.get('priority', 'medium'),
                    category=task_data.get('category'),
                    due_date=due_date
                )
                
                if success:
                    stats['imported'] += 1
                    
                    # 如果有状态信息，更新状态
                    if 'status' in task_data and task_data['status'] in ['in_progress', 'completed']:
                        self.task_service.edit_task(new_task.id, status=task_data['status'])
                else:
                    stats['errors'] += 1
                    
            except Exception as e:
                stats['errors'] += 1
                continue
        
        message = f"导入完成"
        return True, message, stats
    
    def create_backup(self, output_path: Optional[str] = None) -> Tuple[bool, str, Optional[str]]:
        """
        创建数据备份
        
        Args:
            output_path: 输出文件路径
            
        Returns:
            (成功标志, 消息, 备份文件路径)
        """
        try:
            # 生成备份文件名
            if not output_path:
                timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                output_path = f"task_backup_{timestamp}.zip"
            
            # 获取所有任务
            all_tasks = self.task_service.list_tasks()
            
            # 准备备份数据
            backup_data = {
                'backup_info': {
                    'created_at': datetime.now().isoformat(),
                    'version': '1.0',
                    'task_count': len(all_tasks)
                },
                'tasks': []
            }
            
            # 安全处理日期字段
            def safe_date_format(date_obj):
                if date_obj is None:
                    return None
                if hasattr(date_obj, 'isoformat'):
                    return date_obj.isoformat()
                return str(date_obj)
            
            # 转换任务数据
            for task in all_tasks:
                task_dict = {
                    'id': task.id,
                    'title': task.title,
                    'description': task.description,
                    'priority': task.priority,
                    'status': task.status,
                    'category': task.category,
                    'due_date': safe_date_format(task.due_date),
                    'created_at': safe_date_format(task.created_at),
                    'updated_at': safe_date_format(task.updated_at)
                }
                backup_data['tasks'].append(task_dict)
            
            # 创建备份文件
            with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
                # 添加任务数据
                tasks_json = json.dumps(backup_data, ensure_ascii=False, indent=2)
                zipf.writestr('tasks.json', tasks_json)
                
                # 尝试添加数据库文件（如果存在）
                try:
                    db_path = self.task_service.db_manager.db_path
                    if os.path.exists(db_path):
                        zipf.write(db_path, 'database.db')
                except AttributeError:
                    # 如果无法访问数据库路径，跳过数据库文件备份
                    pass
            
            message = f"备份创建成功，包含 {len(all_tasks)} 个任务"
            return True, message, output_path
            
        except Exception as e:
            return False, f"创建备份失败: {str(e)}", None
    
    def restore_backup(self, backup_path: str, mode: str = 'merge') -> Tuple[bool, str, Optional[Dict]]:
        """
        恢复数据备份
        
        Args:
            backup_path: 备份文件路径
            mode: 恢复模式 ('merge', 'replace')
            
        Returns:
            (成功标志, 消息, 统计信息)
        """
        try:
            # 验证备份文件
            if not zipfile.is_zipfile(backup_path):
                return False, "无效的备份文件格式", None
            
            stats = {
                'backup_info': None,
                'tasks_restored': 0
            }
            
            with zipfile.ZipFile(backup_path, 'r') as zipf:
                # 读取任务数据
                if 'tasks.json' not in zipf.namelist():
                    return False, "备份文件中缺少任务数据", None
                
                tasks_data = json.loads(zipf.read('tasks.json').decode('utf-8'))
                stats['backup_info'] = tasks_data.get('backup_info', {})
                
                # 如果是替换模式，先清空现有数据
                if mode == 'replace':
                    # 删除所有现有任务
                    existing_tasks = self.task_service.list_tasks()
                    for task in existing_tasks:
                        self.task_service.delete_task(task.id)
                
                # 导入任务
                import_mode = 'skip' if mode == 'merge' else 'replace'
                success, message, import_stats = self.import_from_json_data(
                    tasks_data.get('tasks', []), 
                    import_mode
                )
                
                if success and import_stats:
                    stats['tasks_restored'] = import_stats['imported'] + import_stats['updated']
            
            message = f"备份恢复成功"
            return True, message, stats
            
        except Exception as e:
            return False, f"恢复备份失败: {str(e)}", None
    
    def generate_report(self, report_type: str) -> Tuple[bool, str, Optional[Dict]]:
        """
        生成数据报告
        
        Args:
            report_type: 报告类型 ('summary', 'detailed', 'productivity')
            
        Returns:
            (成功标志, 消息, 报告数据)
        """
        try:
            report_data = {
                'report_type': report_type,
                'generated_at': datetime.now().isoformat()
            }
            
            if report_type == 'summary':
                report_data.update(self._generate_summary_report())
            elif report_type == 'detailed':
                report_data.update(self._generate_detailed_report())
            elif report_type == 'productivity':
                report_data.update(self._generate_productivity_report())
            else:
                return False, f"不支持的报告类型: {report_type}", None
            
            return True, f"{report_type} 报告生成成功", report_data
            
        except Exception as e:
            return False, f"生成报告失败: {str(e)}", None
    
    def _generate_summary_report(self) -> Dict:
        """生成摘要报告"""
        stats = self.task_service.get_task_statistics()
        all_tasks = self.task_service.list_tasks()
        
        # 按分类统计
        categories = {}
        for task in all_tasks:
            category = task.category or '未分类'
            if category not in categories:
                categories[category] = {'total': 0, 'completed': 0, 'completion_rate': 0}
            
            categories[category]['total'] += 1
            if task.status == 'completed':
                categories[category]['completed'] += 1
        
        # 计算分类完成率
        for category in categories:
            if categories[category]['total'] > 0:
                rate = (categories[category]['completed'] / categories[category]['total']) * 100
                categories[category]['completion_rate'] = round(rate, 1)
        
        # 过期和即将到期任务
        overdue_tasks = len([t for t in all_tasks if t.is_overdue()])
        
        upcoming_tasks = 0
        today = datetime.now().date()
        week_later = today + timedelta(days=7)
        
        for task in all_tasks:
            if task.due_date:
                try:
                    # 确保 due_date 是 date 对象
                    if isinstance(task.due_date, str):
                        due_date = datetime.strptime(task.due_date, '%Y-%m-%d').date()
                    elif hasattr(task.due_date, 'date'):
                        due_date = task.due_date.date()
                    else:
                        due_date = task.due_date
                    
                    if due_date > today and due_date <= week_later:
                        upcoming_tasks += 1
                except:
                    pass
        
        return {
            'overview': stats,
            'categories': categories,
            'overdue_tasks': overdue_tasks,
            'upcoming_tasks': upcoming_tasks
        }
    
    def _generate_detailed_report(self) -> Dict:
        """生成详细报告"""
        all_tasks = self.task_service.list_tasks()
        
        # 按状态分组
        tasks_by_status = {
            'todo': [],
            'in_progress': [],
            'completed': []
        }
        
        for task in all_tasks:
            task_dict = {
                'id': task.id,
                'title': task.title,
                'priority': task.priority,
                'category': task.category,
                'due_date': task.due_date.isoformat() if task.due_date else None,
                'created_at': task.created_at.isoformat() if hasattr(task.created_at, 'isoformat') else str(task.created_at),
                'is_overdue': task.is_overdue()
            }
            tasks_by_status[task.status].append(task_dict)
        
        # 按优先级分组
        tasks_by_priority = {
            'high': [],
            'medium': [],
            'low': []
        }
        
        for task in all_tasks:
            task_dict = {
                'id': task.id,
                'title': task.title,
                'status': task.status,
                'category': task.category,
                'due_date': task.due_date.isoformat() if task.due_date else None
            }
            tasks_by_priority[task.priority].append(task_dict)
        
        return {
            'tasks_by_status': tasks_by_status,
            'tasks_by_priority': tasks_by_priority,
            'total_tasks': len(all_tasks)
        }
    
    def _generate_productivity_report(self) -> Dict:
        """生成生产力报告"""
        all_tasks = self.task_service.list_tasks()
        completed_tasks = [t for t in all_tasks if t.status == 'completed']
        
        # 计算平均完成时间
        completion_times = []
        for task in completed_tasks:
            if task.due_date:
                # 计算从创建到完成的天数
                try:
                    if hasattr(task.updated_at, 'date'):
                        updated_date = task.updated_at.date()
                    else:
                        updated_date = datetime.strptime(str(task.updated_at), '%Y-%m-%d').date()
                    
                    if hasattr(task.created_at, 'date'):
                        created_date = task.created_at.date()
                    else:
                        created_date = datetime.strptime(str(task.created_at), '%Y-%m-%d').date()
                    
                    days = (updated_date - created_date).days
                    completion_times.append(days)
                except:
                    pass
        
        avg_completion_time = None
        if completion_times:
            avg_completion_time = round(sum(completion_times) / len(completion_times), 1)
        
        # 按日期统计完成任务
        daily_completions = {}
        for task in completed_tasks:
            try:
                if hasattr(task.updated_at, 'date'):
                    date_str = task.updated_at.date().isoformat()
                else:
                    date_str = str(task.updated_at)
                daily_completions[date_str] = daily_completions.get(date_str, 0) + 1
            except:
                pass
        
        # 找出最高效的日期
        most_productive_day = None
        if daily_completions:
            most_productive_day = max(daily_completions.items(), key=lambda x: x[1])
        
        # 按分类统计完成任务
        category_completions = {}
        for task in completed_tasks:
            category = task.category or '未分类'
            category_completions[category] = category_completions.get(category, 0) + 1
        
        # 找出最高效的分类
        most_productive_category = None
        if category_completions:
            most_productive_category = max(category_completions.items(), key=lambda x: x[1])
        
        return {
            'total_completed': len(completed_tasks),
            'avg_completion_time_days': avg_completion_time,
            'daily_completions': daily_completions,
            'most_productive_day': most_productive_day,
            'category_completions': category_completions,
            'most_productive_category': most_productive_category
        }
    
    def cleanup_database(self) -> Tuple[bool, str, Optional[Dict]]:
        """
        清理数据库
        
        Returns:
            (成功标志, 消息, 统计信息)
        """
        try:
            # 获取已完成任务
            completed_tasks = self.task_service.list_tasks(status='completed')
            
            # 删除30天前完成的任务
            cutoff_date = datetime.now() - timedelta(days=30)
            old_completed_tasks = []
            
            for task in completed_tasks:
                try:
                    if hasattr(task.updated_at, 'date'):
                        task_date = task.updated_at
                    else:
                        task_date = datetime.strptime(str(task.updated_at), '%Y-%m-%d %H:%M:%S')
                    
                    if task_date < cutoff_date:
                        old_completed_tasks.append(task)
                except:
                    pass
            
            deleted_count = 0
            for task in old_completed_tasks:
                success, _ = self.task_service.delete_task(task.id)
                if success:
                    deleted_count += 1
            
            # 优化数据库
            try:
                self.task_service.db_manager.execute_query("VACUUM")
                database_optimized = True
            except:
                database_optimized = False
            
            stats = {
                'completed_tasks_removed': deleted_count,
                'database_optimized': database_optimized
            }
            
            message = f"数据库清理完成"
            return True, message, stats
            
        except Exception as e:
            return False, f"数据库清理失败: {str(e)}", None